package cn.kent.high.juc.threadPool;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * {@link java.util.concurrent.ScheduledThreadPoolExecutor}
 * 继承并实现了extends ThreadPoolExecutor implements ScheduledExecutorService
 * 内部维护了 {@link java.util.concurrent.ScheduledThreadPoolExecutor.DelayedWorkQueue}， 类似{@link java.util.concurrent.DelayQueue},是一个延迟队列
 *
 * ScheduledFutureTask 内部变量说明： state 状态变量 period 任务类型 =0执行一次结束 >0固定频率 <0 固定延迟
 *     private volatile int state;
 *     private static final int NEW          = 0; // 新建
 *     private static final int COMPLETING   = 1; // 运行中
 *     private static final int NORMAL       = 2; // 正常运行结束
 *     private static final int EXCEPTIONAL  = 3; // 运行中异常
 *     private static final int CANCELLED    = 4; // 任务被取消
 *     private static final int INTERRUPTING = 5; // 任务正在被中断
 *     private static final int INTERRUPTED  = 6; // 任务已被中断
 *
 *      public void run(){
 *          boolean periodic=isPeriodic(); // 是否是周期性执行的线程
 *          if(!canRunInCurrentRunState(periodic)) // 取消任务
 *              cancel(false);
 *          else if(!periodic) // 只执行一次，当调用schedule()方法时
 *              ScheduledFutureTask.super.run();
 *          else if(ScheduledFutureTask.super.runAndReset()){ // 定时执行
 *              setNextRunTime(); // 设置时间为当前时间+定时时间 time+=period
 *              reExecutePeriodic(outerTask); // 重新加入该任务到delay队列
 *          }
 *      }
 *
 * 重点方法：
 * {@link java.util.concurrent.ScheduledThreadPoolExecutor#schedule(Runnable, long, TimeUnit)}
 *      public ScheduledFuture<?> schedule(Runnable command,
 *                                        long delay,
 *                                        TimeUnit unit) {
 *         if (command == null || unit == null) // 参数校验
 *             throw new NullPointerException();
 *         RunnableScheduledFuture<?> t = decorateTask(command, // 任务转换
 *             new ScheduledFutureTask<Void>(command, null,
 *                                           triggerTime(delay, unit)));
 *         delayedExecute(t); // 添加任务到延迟队列
 *         return t;
 *     }
 * {@link java.util.concurrent.ScheduledThreadPoolExecutor#scheduleAtFixedRate(Runnable, long, long, TimeUnit)} // 按照固定频率执行
 *      public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
 *                                                   long initialDelay,
 *                                                   long period,
 *                                                   TimeUnit unit) {
 *         if (command == null || unit == null) // 校验
 *             throw new NullPointerException();
 *         if (period <= 0)
 *             throw new IllegalArgumentException();
 *         ScheduledFutureTask<Void> sft =
 *             new ScheduledFutureTask<Void>(command,
 *                                           null,
 *                                           triggerTime(initialDelay, unit),
 *                                           unit.toNanos(period));
 *         RunnableScheduledFuture<Void> t = decorateTask(command, sft);
 *         sft.outerTask = t;
 *         delayedExecute(t);
 *         return t;
 *     }
 *
 *     private void delayedExecute(RunnableScheduledFuture<?> task) {
 *         if (isShutdown()) // 如果线程池关闭了，走拒绝策略
 *             reject(task);
 *         else {
 *             super.getQueue().add(task); // 添加任务到延迟队列
 *             if (isShutdown() && // 再次检查线程池状态
 *                 !canRunInCurrentRunState(task.isPeriodic()) &&
 *                 remove(task))
 *                 task.cancel(false);
 *             else
 *                 ensurePrestart(); // 确保至少有一个线程在运行
 *         }
 *     }
 *
 *     void ensurePrestart() {
 *         int wc = workerCountOf(ctl.get());
 *         if (wc < corePoolSize) // 增加核心线程数
 *         else if (wc == 0) // 如果初始化 corePoolSize==0，那么就再加一个线程
 *             addWorker(null, true);
 *             addWorker(null, false);
 *     }
 *
 * {@link java.util.concurrent.ScheduledThreadPoolExecutor#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)} 按照固定时间间隔执行
 *      public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
 *                                                      long initialDelay,
 *                                                      long delay,
 *                                                      TimeUnit unit) {
 *         if (command == null || unit == null) // 参数校验
 *             throw new NullPointerException();
 *         if (delay <= 0)
 *             throw new IllegalArgumentException();
 *         ScheduledFutureTask<Void> sft = // 任务转换，这里是-delay -> 可重复执行的任务
 *             new ScheduledFutureTask<Void>(command,
 *                                           null,
 *                                           triggerTime(initialDelay, unit),
 *                                           unit.toNanos(-delay));
 *         RunnableScheduledFuture<Void> t = decorateTask(command, sft);
 *         sft.outerTask = t;
 *         delayedExecute(t); // 添加任务到队列
 *         return t;
 *     }
 */
public class ScheduledThreadPoolExecutorTest {
    public static void main(String[] args) {
        // 工具类创建线程池
        // ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
        // new ScheduledThreadPoolExecutor(0);

        AtomicLong aLong = new AtomicLong();
        System.out.println(aLong.get());
        aLong.getAndIncrement();
        System.out.println(aLong.getAndIncrement());
    }
}
